<template>
  <div class="page-controller">
    <div class="canvas"></div>
  </div>
</template>
<script setup>
import * as Three from "three";
import {onMounted, onUnmounted, reactive, watch, onActivated, onDeactivated} from 'vue';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
import {GUI} from 'dat.gui';
let state = reactive({
  gui: null,
  taskFlag: true,
  axesFlag: true,
  alpha: 0.5,
  cubeColor: '#1dd1a1',
  position: {x: 0, y: 0, z: 0},
  rotate: {x: 0, y: 0, z: 0,},
  scale: {x: 1, y: 1, z: 1,},
});
// 创建场景
let scene = new Three.Scene();
// 创建坐标轴
let axes = new Three.AxesHelper(5);
// 创建结构
let cubeGeometry = new Three.BoxGeometry(1, 1, 1,);
// 创建材质
let cubeMaterial = new Three.MeshBasicMaterial({color: state.cubeColor});
// 根据结构和材质创建物体
let cube = new Three.Mesh(cubeGeometry, cubeMaterial);
// 创建渲染器，开启平滑，允许设置透明度
let renderer = new Three.WebGLRenderer({antialias: true, alpha: true});
// 渲染器设置颜色和透明度
renderer.setClearColor('#c7ecee',);
renderer.setClearAlpha(state.alpha);
onMounted(() => {
  let dom = document.getElementsByClassName('canvas')[0];
  let width = dom.clientWidth;
  let height = dom.clientHeight;
  // 创建相机
  let camera = new Three.PerspectiveCamera(75, width / height, 0.1, 1000);
  // 设置相机位置
  camera.position.set(0, 0, 10);
  // 场景添加相机
  scene.add(camera);
  // 场景添加坐标轴
  scene.add(axes);
  // 场景添加物体
  scene.add(cube);
  // 渲染器设置大小
  renderer.setSize(width, height);
  // 将渲染dom加入页面
  dom.appendChild(renderer.domElement);
  // 根据相机和渲染器渲染元素创建控制器
  let controller = new OrbitControls(camera, renderer.domElement);
  // 控制器设置阻尼
  controller.enableDamping = true;
  // 持续渲染
  function render() {
    controller.update();
    // 通过渲染器将场景渲染到相机
    renderer.render(scene, camera);
    state.taskFlag && requestAnimationFrame(render);
  }
  render();
});
onUnmounted(() => {
  state.taskFlag = false;
});
onActivated(() => {
  let gui = new GUI();
  gui.add(state, 'axesFlag').name('坐标轴').onChange(val => axes.visible = val);
  gui.add(state, 'alpha').name('透明度').max(1).min(0).step(0.1).onChange(val => renderer.setClearAlpha(val));
  gui.addColor(state, 'cubeColor').name('物体颜色').onChange(val => cube.material.color.set(val));
  let position = gui.addFolder('移动');
  position.add(cube.position, 'x').max(2).min(-2).step(0.01);
  position.add(cube.position, 'y').max(2).min(-2).step(0.01);
  position.add(cube.position, 'z').max(2).min(-2).step(0.01);
  position.open();
  let scale = gui.addFolder('缩放');
  scale.add(cube.scale, 'x').max(2).min(0.5).step(0.01);
  scale.add(cube.scale, 'y').max(2).min(0.5).step(0.01);
  scale.add(cube.scale, 'z').max(2).min(0.5).step(0.01);
  scale.open();
  let rotation = gui.addFolder('旋转');
  rotation.add(cube.rotation, 'x').max(Math.PI).min(-Math.PI).step(0.01);
  rotation.add(cube.rotation, 'y').max(Math.PI).min(-Math.PI).step(0.01);
  rotation.add(cube.rotation, 'z').max(Math.PI).min(-Math.PI).step(0.01);
  rotation.open();
  state.gui = gui;
});
onDeactivated(() => {
  state.gui.destroy();
});
</script>
<style lang="scss">
.page-controller {
  .canvas {
    width: 100%;
    height: 100%;
  }
}
</style>